﻿using ldhWebApi.models;
using MongoDB.Bson;
using MongoDB.Driver;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Cors;
using System.Web.Http.Description;

namespace ldhWebApi.Controller
{
    // Allow CORS for all origins. (Caution!)
    [EnableCors(origins: "*", headers: "*", methods: "*")]
    //[EnableCors(origins: "http://www.contoso.com,http://www.example.com", headers: "accept,content-type,origin,x-my-header", methods: "get,post")]
    [RoutePrefix("api")]
    public class BooksController : ApiController
    {
        IMongoDatabase db = ldhWebApi.database.BaseManager.GetDataBase("Bookdb");
        IMongoCollection<Book> books;

        public BooksController()
        {
            books = db.GetCollection<Book>("Books");
        }

        //customer api
        [Route("customers/{customerId}/orders/{orderId}")]
        public string GetOrderByCustomer(int customerId, int orderId) 
        {
            BsonDocument bd=new BsonDocument();
            bd.AddRange(new BsonDocument("a", customerId));
            bd.AddRange(new BsonDocument("b", orderId));
            return bd.ToJson();
        }

        [Route("report/fileupload/{rpname}")]
        public async Task<IHttpActionResult> UploadFile(string rpname)
        {
            if (!Request.Content.IsMimeMultipartContent())
            {
                return StatusCode(HttpStatusCode.UnsupportedMediaType);
            }
            var filesReadToProvider = await Request.Content.ReadAsMultipartAsync();
            string file = AppDomain.CurrentDomain.BaseDirectory + rpname;
            foreach (var stream in filesReadToProvider.Contents)
            {
                var fileBytes = await stream.ReadAsByteArrayAsync();
                var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write);
                fileStream.Write(fileBytes, 0, fileBytes.Length);
                fileStream.Close();
            }
            return Ok();
        }

        [Route("report/file/{rpname}")]
        public HttpResponseMessage GetReportFile(string rpname)
        {
            if (String.IsNullOrEmpty(rpname))
                return Request.CreateResponse(HttpStatusCode.BadRequest);

            string file = AppDomain.CurrentDomain.BaseDirectory + rpname;
            if (!File.Exists(file))
                return Request.CreateResponse(HttpStatusCode.BadRequest);

            var result = Request.CreateResponse(HttpStatusCode.OK);
            result.Content = new StreamContent(new FileStream(file, FileMode.Open, FileAccess.Read));
            result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
            result.Content.Headers.ContentDisposition.FileName = rpname;
            result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
            return result;
        }

        //[ActionName("DefaultAction")] //Map Action and you can name your method with any text
        // GET api/books
        //[DeflateCompression]//using zlib compression
        [Route("books")]
        public async Task<IHttpActionResult> GetBooks()
        {
            //禁止使用decimal，转用double型
            //var names = await books
            //    .Find(x => x.Price >50 && x.Price <300)
            //    .ToListAsync();
            //return Ok(names);

            //日期时间操作提交时必须是utc时间
            //日期时间查询时必须先转为本地时间
            var start = DateTime.Parse("2015-07-11T15:07:41").ToLocalTime();
            var end = DateTime.Parse("2015-07-12T03:01:37").ToLocalTime();
            var names = await books.Find(x => x.ReleaseDate >= start && x.ReleaseDate <= end).ToListAsync();
            return Ok(names);

            //var bks = await books.Find(new BsonDocument()).ToListAsync();
            //return Ok(bks);
        }

        //// GET api/books/1
        //[Route("books/{id}")]
        //public async Task<IHttpActionResult> GetByTitle(string id)
        //{
        //    var any = await books
        //        .Find(x => x.Title == id)
        //        .SortBy(x => x.Price)
        //        .Project(x => x.Genre + " " + x.Title)
        //        .ToListAsync();
        //    return Ok(any);
        //}

        //// GET api/books/5
        [Route("books/{id}")]
        //[ResponseType(typeof(Book))]
        public async Task<IHttpActionResult> GetBook(string id)
        {
            //身份验证
            //var pwd = Request.Headers.SingleOrDefault(h => h.Key == "pwd");
            //if (pwd.Value.FirstOrDefault() != "123")
            //{
            //    return StatusCode(HttpStatusCode.NotFound);
            //}
            ObjectId oid;
            if (!ObjectId.TryParse(id, out oid))
            {
                return StatusCode(HttpStatusCode.Unused);
            }
            var book = await books.Find(new BsonDocument("_id",oid)).FirstOrDefaultAsync();
            if (book == null)
            {
                return NotFound();
            }

            //return Ok(book);
            return Ok(book.ToJson());
        }

        // PUT api/books/5
        [Route("books/{id}")]
        [HttpPut]
        public async Task<IHttpActionResult> PutBook(string id, Book book)
        {
            //if (!ModelState.IsValid)
            //{
            //    return BadRequest(ModelState);
            //}

            //if (ObjectId.Parse(id) != book.Id)
            //{
            //    return BadRequest();
            //}

            //var result = await books.UpdateOneAsync(x => x.Id == ObjectId.Parse(id), Builders<Book>.Update.Set(x => x, book)); 
            var dbbook = await books.Find(x => x.Id == ObjectId.Parse(id)).SingleAsync();
            dbbook.Genre = book.Genre;
            dbbook.Price = book.Price;
            //dbbook.ReleaseDate = book.ReleaseDate.AddHours(8);
            dbbook.Title = book.Title;
            var result = await books.ReplaceOneAsync(x => x.Id == ObjectId.Parse(id), dbbook);
            return StatusCode(HttpStatusCode.NoContent);
        }

        //// POST api/BookApi
        //[ActionName("DefaultAction")]
        [Route("books")]
        [HttpPost]
        [ResponseType(typeof(Book))]
        public async Task<IHttpActionResult> PostBook(Book book)
        {
            //if (!ModelState.IsValid)
            //{
            //    return BadRequest(ModelState);
            //}
            //时区+8
            //book.ReleaseDate = book.ReleaseDate.AddHours(8);
            await books.InsertOneAsync(book);

            return Ok(book.ToJson());
        }

        // DELETE api/BookApi/5
        [Route("books/{id}")]
        [HttpDelete]
        [ResponseType(typeof(Book))]
        public async Task<IHttpActionResult> DeleteBook(string id)
        {
            if (!await BookExists(id))
            {
                return NotFound();
            }

            var result = await books.DeleteOneAsync(x => x.Id == ObjectId.Parse(id));

            return Ok(result);
        }

        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);
        }

        private async Task<bool> BookExists(string id)
        {
            var c = await books.CountAsync<Book>(e => e.Id == ObjectId.Parse(id));
            if (c > 0)
            {
                return true;
            }
            return false;
        }
    }
}
